﻿#include "HiPicShare.h"
 #include <unistd.h>
 #include <string.h>

static const int EXTENDS_LEN = 100;
static const int MAX_VECTOR_LEN = 100;

static void defaultShareFun(const uint8_t*, uint32_t) {}

static void* run_fun(void*);

HiPicShare::HiPicShare() : shareFunction(defaultShareFun) {
}

HiPicShare::~HiPicShare() {
	this->Stop();
}

bool HiPicShare::Start(uint32_t width, uint32_t shareSize, const SHARE_FUN& share_fun){	
	this->shareFunction = share_fun;
	this->startWidth = width;
	this->shareSize = shareSize;

	bgrHeap.Init(MAX_VECTOR_LEN, [&](){
			return new uint8_t[shareSize + EXTENDS_LEN];
		}, [&](void* buf){
			delete[] buf;
	});

	pthread_create(&shareThread, NULL,  run_fun, this);
}

void HiPicShare::onThread() {
	while (!isExit) {
		HandlePic();
		usleep(20000);
	}
}

void HiPicShare::Stop() {
	if (0 == shareThread) {
		pthread_join(shareThread, NULL);
		shareThread = 0;
	}
	size_t size = bgrList.size();
	for (int i = 0; i < size; i++) {
		this->AbandonFrontPic();
	}
}
void HiPicShare::OnPic(const uint8_t *bgr, uint32_t width, uint32_t height) {
	if (bgrList.size() > 100) {
		return;
	}

	if (width != this->startWidth) {
		return;
	}

	uint8_t* buf = (uint8_t*)this->bgrHeap.CreateData();
	if (nullptr == buf) {
		return;
	}
	::memcpy(buf, bgr, this->shareSize);
	bgrList.push_back(buf);	
}

void HiPicShare::HandlePic(){
	size_t size = bgrList.size();
	if (size < 1) {
		return;
	}
	if (size <= 20) {
		this->HandleFrontPic();
		return;
	}

	if (size <= 50) {       
		this->AbandonFrontPic();
		this->HandleFrontPic();
		return;
	}

	int abandonNum = size - 50;
	for (int i = 0; i < abandonNum; i++) {
		this->AbandonFrontPic();
	}

	this->HandleFrontPic();
}

void HiPicShare::HandleFrontPic() {
	uint8_t* buf = readFrontPic();
	if (nullptr == buf) {
		return;
	}
	this->shareFunction(buf, this->shareSize);
	bgrHeap.Release(buf);
	return;	
}

void HiPicShare::AbandonFrontPic() {
	uint8_t* buf = readFrontPic();
	bgrHeap.Release(buf);
}

uint8_t* HiPicShare::readFrontPic(){
	size_t size = bgrList.size();
	if (size < 1) {
		return nullptr;
	}
	auto it = bgrList.begin();
	uint8_t* buf = *it;
	bgrList.erase(it);
	return buf;
}

static void* run_fun(void* arg) {
	HiPicShare* tf = static_cast<HiPicShare*>(arg);
	tf->onThread();
	return NULL;
}